/*
 * By: Werner Schuster (murphee)
 * 
 * Copyright (c) 2005-2006 Werner Schuster (murphee)
 * 
 * This file is part of the EclipseShell project. EclipseShell is subject 
 * to the Eclipse Public License (EPL) available at
 * http://www.eclipse.org/org/documents/epl-v10.php
 * or in the file /epl-v10.html in the source for other info
 * see the /eclipseshell.license file
 */
package net.sf.eclipseshell.editors;

import net.sf.eclipseshell.EclipseShellPlugin;
import net.sf.eclipseshell.internal.actions.LaunchNewShell;
import net.sf.eclipseshell.internal.actions.LaunchNewShell.ShellEditorInput;
import net.sf.eclipseshell.internal.extensions.ExecutionProviderManager;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.jface.text.source.AnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.editors.text.FileDocumentProvider;

public class BeanshellDocumentProvider extends FileDocumentProvider {

	protected IDocument createDocument(Object element) throws CoreException {
		IDocument document = super.createDocument(element);
		
		if(document == null){
			document = createEmptyDocument();
		}
		
		filterDocument(document, element);
				
		if (document != null) {
			IDocumentPartitioner partitioner =
				new FastPartitioner(
					new BeanshellPartitionScanner(),
					new String[] {
						BeanshellPartitionScanner.COMMENT });
			partitioner.connect(document);
			document.setDocumentPartitioner(partitioner);
		}
		return document;
	}
	
	private void filterDocument(IDocument doc, Object element) {
		doc.addPositionCategory(InterpreterEditor.REGION_POSITION_TYPE);
		String contents = doc.get();
		String extension = "";
		if (element instanceof IFileEditorInput) {
			IFileEditorInput fileInput = (IFileEditorInput) element;
			extension = fileInput.getFile().getFileExtension();
		} else if (element instanceof LaunchNewShell.ShellEditorInput) {
			LaunchNewShell.ShellEditorInput shellInput = (LaunchNewShell.ShellEditorInput) element;
			extension = shellInput.getExtensionName();
			return;
		}
		String[] delimiterTuple = ExecutionProviderManager.getRegionDelimiterRegexForFileExtension(extension);

		if(delimiterTuple != null){
			String regionDelimiter = delimiterTuple[1];
			String [] parts = contents.split(regionDelimiter, -1);
			doc.set("");
			doc.addPositionCategory(InterpreterEditor.REGION_POSITION_TYPE);
			// The 2nd part of the if needs to be there, because String.split seems
			// to return an 1-element array even if the split string was empty!
			if(parts.length > 0 && (parts[0].length() > 0)){
				// insert the region
				int regionOffset = 0;
				
				for (int i = 0; i < parts.length; i++) {
					String currRegion = parts[i];
					try {
						doc.replace(regionOffset,0, currRegion);
						Position newRegion = new Position(regionOffset, currRegion.length());
						regionOffset += currRegion.length();
						doc.addPosition(InterpreterEditor.REGION_POSITION_TYPE, newRegion);
					} catch (BadLocationException e) {
						EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
					} catch (BadPositionCategoryException e) {
						EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
					}
				}
				if(regionOffset == doc.getLength()){
					try {
						doc.replace(doc.getLength(), 0, "\n\n");
					} catch (BadLocationException e) {
						EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
					}
				}
			}
			
			
		}
	}

	protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
		IDocument docToSave = createEmptyDocument();
		Position[] regions;
		String extension = "";
		if (element instanceof IFileEditorInput) {
			IFileEditorInput fileInput = (IFileEditorInput) element;
			extension = fileInput.getFile().getFileExtension();
		}
		if (element instanceof ShellEditorInput) {
			ShellEditorInput fileInput = (ShellEditorInput) element;
			extension = fileInput.getExtensionName();
		}
		
		String[] delimiterTuple = ExecutionProviderManager.getRegionDelimiterRegexForFileExtension(extension);
		// TODO: can cause NPEs if no 0th element is available or if array is null
		String delimiter = delimiterTuple[0];
		
		try {
			regions = document.getPositions(InterpreterEditor.REGION_POSITION_TYPE);
			if(regions != null){
				for (int i = 0; i < regions.length; i++) {
					Position currRegion = regions[i];
					String contents = document.get(currRegion.getOffset(), currRegion.getLength());
					docToSave.replace(docToSave.getLength(), 0, contents);
					docToSave.replace(docToSave.getLength(), 0, delimiter);
				}
			}
			docToSave.replace(docToSave.getLength(), 0, "\n\n");
		} catch (BadPositionCategoryException e) {
			EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
		} catch (BadLocationException e) {
			EclipseShellPlugin.getDefault().log(Status.WARNING, e.getLocalizedMessage(), e);
		}
		
		
		
		super.doSaveDocument(monitor, element, docToSave, overwrite);
	}
	
	public IAnnotationModel getAnnotationModel(Object element) {
	
		if (element instanceof LaunchNewShell.ShellEditorInput) {
			LaunchNewShell.ShellEditorInput inp = (LaunchNewShell.ShellEditorInput) element;
			return new AnnotationModel();
		}
		return super.getAnnotationModel(element);
		
	}
	
	
}